//
//  DDHdrCloud.m
//  MyClouds
//
//  Created by sarah doo on 13-8-11.
//  Copyright (c) 2013年 sarah doo. All rights reserved.
//

#import "DDHdrCloud.h"

@implementation DDHdrCloud

@synthesize signature, hdrs, version, cmd, crc, length,entity;

- (id)initWithData:(NSData *)data {
    self = [super init];
    if (self) {
        self.entity = [[NSMutableData alloc]init];
        [self.entity appendData:data];
    }
    return self;
}

- (id)init {
    self = [super init];
    self.entity = [[NSMutableData alloc]init];
    if (self) {
        [self setSignature:CLOUD_SIGNATURE];
        [self setVersion:CLOUD_VERSION_1_0];
        [self setCrc:0];
        [self setCmd:0];
        [self setLength:0];
        
    }
    return self;
}

- (void)dealloc {
//    [self.signature release];
//    [self.entity release];
//    [self.hdrs release];
    self.signature = nil;
    self.entity = nil;
    self.hdrs = nil;
    [super dealloc];
}

#pragma - mark publics

//NSData转int

- (int)dataToInt:(NSData *)subData {
    //Byte *b=(Byte *)[subData bytes];
    int temp = 0;
    [subData getBytes:&temp length:sizeof(temp)];
    return temp;
}


//计算CRC

- (int)crcs:(NSData *)da withLength:(int)lengths{
    int l, h, t;
    l = 0x000000ff;
    h = 0x000000ff;
    Byte *data = (Byte *)[da bytes];
    for (int i = 0; i < lengths; i++) {
        h ^= data[i];
        h &= 0x000000ff;
        h ^= h >> 4;
        h &= 0x000000ff;
        t = h;
        h = l;
        l = t;
        t = ((l << 4) | (l >> 4));
        t &= 0x000000ff;
        h ^= ((t << 2) | (t >> 6)) & 0x0000001f;
        h &= 0x000000ff;
        h ^= t & 0x000000f0;
        h &= 0x000000ff;
        l ^= ((t << 1) | (t >> 7)) & 0x000000e0;
        l &= 0x000000ff;
    }
    h &= 0x000000ff;
    l &= 0x000000ff;
    return (h << 8) | l;
}


//验证CRC
- (BOOL)verifyCRC:(NSData *)data {
    NSRange range ;
    range.location = 8;
    range.length = 4;
    NSData *crcData = [data subdataWithRange:range];
    NSLog(@"crcData ------ %@",crcData);
    int verifyC = [self dataToInt:crcData];
    int x = 0;
    NSData *crcDatas = [NSData dataWithBytes:&x length:sizeof(x)];
    range.location = 0;
    range.length = 8;
    NSData *before = [data subdataWithRange:range];
    NSMutableData *lastData = [NSMutableData dataWithData:before];
    [lastData appendData:crcDatas];
    range.location = 12;
    range.length = data.length - 12;
    NSData *later = [data subdataWithRange:range];
    [lastData appendData:later];
    int newCRC = [self crcs:lastData withLength:[data length]];
    if (verifyC == newCRC) 
        return YES;
    else 
        return NO;
}

//NSData转string

- (NSString *)dataToString:(NSData *)data {
    NSString *test = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    return [test autorelease];
}

//int转NSData
- (NSData *)intToData:(int)i{
    NSData* data = [[NSData alloc]initWithBytes:&i length:INT_SIZE];
    return data;
}


//字节倒序排列

- (NSData *)sortData:(NSData *)data {
    Byte *byte = (Byte *)[data bytes];
    NSMutableData *last = [NSMutableData dataWithCapacity:10];
    for (int i = [data length] - 1; i >= 0; i--) {
        Byte x = byte[i];
        NSData *data = [NSData dataWithBytes:&x length:sizeof(x)];
        [last appendData:data];
    }
    return last;
}

//发送searchAll指令的时候需要制定消息头。

- (NSData *)hdrData {
    int tmpCRC = 0;
    NSData *sign = [self.signature dataUsingEncoding:NSUTF8StringEncoding];
    NSData *useSign = [self sortData:sign];
    NSData *tmpCRCData = [NSData dataWithBytes:&tmpCRC length:sizeof(tmpCRC)];
    NSData *cmdData = [NSData dataWithBytes:&cmd length:sizeof(cmd)];
    NSData *lengthData = [NSData dataWithBytes:&length length:sizeof(length)];
    NSData *versionData = [NSData dataWithBytes:&version length:sizeof(version)];
    NSMutableData *calculateCRC = [NSMutableData dataWithData:useSign];
    [calculateCRC appendData:versionData];
    [calculateCRC appendData:tmpCRCData];
    [calculateCRC appendData:cmdData];
    [calculateCRC appendData:lengthData];
    int newCRC = [self crcs:calculateCRC withLength:20];
    NSData *newCRCData = [NSData dataWithBytes:&newCRC length:sizeof(newCRC)];
    NSMutableData *newHDRData = [NSMutableData dataWithData:useSign];
    [newHDRData appendData:versionData];
    [newHDRData appendData:newCRCData];
    [newHDRData appendData:cmdData];
    [newHDRData appendData:lengthData];
    NSLog(@"newHDRData --------- %@",newHDRData);
    return newHDRData;
}

#pragma - mark setter/getter
- (void)setSignature:(NSString *)_signature {
    if (signature != _signature) {
        [signature release];
        signature = [_signature retain];
    }
    NSRange range;
    range.location = 0;
    range.length = 4;
    NSData* signData = [CLOUD_SIGNATURE dataUsingEncoding:NSASCIIStringEncoding];
    signData = [self sortData:signData];
    [entity replaceBytesInRange:range withBytes:[signData bytes]];
//    [entity appendData:signData];
}

- (NSString *)signature {
    if (self.entity) {
        NSRange range;
        range.location = 0;
        range.length = 4;
        NSData *signatureData = [self.entity subdataWithRange:range];
        return [self dataToString:signatureData];
        
    } else
        return signature;
}

- (void)setVersion:(int)_version {
    if (version != _version) {
        version = _version;
    }
    
    NSData* versionData =[NSData dataWithBytes:&version length:sizeof(CLOUD_VERSION_1_0)];
    NSRange range;
    range.location = 4;
    range.length = 4;
    [entity replaceBytesInRange:range withBytes:[versionData bytes]];
    //[entity appendData:versionData];
    
}

- (int)version {
    if (self.entity) {
        NSRange range;
        range.location = 4;
        range.length = 4;
        NSData *versionData = [self.entity subdataWithRange:range];
        int versions = [self dataToInt:versionData];
        return versions;
    } else {
        return version;
    }
    
}

- (void)setCrc:(int)_crc {
    if (crc != _crc) {
        crc = _crc;
    }
    
    NSData* crcData = [NSData dataWithBytes:&crc length:sizeof(crc)];
    NSRange range;
    range.location = 8;
    range.length = 4;
    [entity replaceBytesInRange:range withBytes:[crcData bytes]];
    //[entity appendData:crcData];
}

- (int)crc {
    if (self.entity) {
        NSRange range;
        range.location = 8;
        range.length = 4;
        NSData *crcDatas = [self.entity subdataWithRange:range];
        return [self dataToInt:crcDatas];
    } else
        return crc;
}

- (void)setCmd:(int)_cmds {
    if(cmd != _cmds) {
        cmd = _cmds;
    }
    
    NSData* cmdData = [NSData dataWithBytes:&cmd length:sizeof(cmd)];
    NSRange range;
    range.location = 12;
    range.length = 4;
    [entity replaceBytesInRange:range withBytes:[cmdData bytes]];
    //[entity appendData:cmdData];
}

- (int)cmd {
    if (self.entity) {
        NSRange range;
        range.length = 4;
        range.location = 12;
        NSData *cmdDatas = [self.entity subdataWithRange:range];
        int cmds = [self dataToInt:cmdDatas];
        return cmds;
    } else {
        return cmd;
    }
    
}

- (void)setLength:(int)_length {
    if (length != _length) {
        length = _length;
    }
    
    //length = CFSwapInt32HostToBig(length);
    NSData* lengthData = [NSData dataWithBytes:&length length:sizeof(length)];
    NSRange range;
    range.length = 4;
    range.location =16;
    [entity replaceBytesInRange:range withBytes:[lengthData bytes]];
    //[entity appendData:lengthData];
}

- (int)length {
    if (self.entity) {
        NSRange range;
        range.location = 16;
        range.length = 4;
        NSData *lengthData = [self.entity subdataWithRange:range];
        return [self dataToInt:lengthData];
    } else
        return length;
    
}

//-(void)dealloc{
//    
//}

- (void) printHead
{
    NSLog(@"sign:%@,versin:%d,cmd:%d,crc:%d,length:%d",[self signature],[self version],[self cmd],[self crc],[self length]);
}
@end
